package com.me.study.javaCore.dynamicProxy.javassist;

import com.me.study.javaCore.dynamicProxy.ITarget;
import com.me.study.javaCore.dynamicProxy.PerformanceMonitor;
import com.me.study.javaCore.dynamicProxy.TargetImpl;
import javassist.util.proxy.MethodFilter;
import javassist.util.proxy.Proxy;
import javassist.util.proxy.ProxyFactory;
import org.junit.Test;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.nio.file.Paths;

/**
 * javassist Proxy 动态代理：MethodHandler
 * javassist Bytecode Proxy 动态代理：
 */
public class TestJavassist {

    @Test
    public void testBytecodeProxy() throws Exception {
        ITarget target = new TargetImpl();
        ITarget proxy = (ITarget) ProxyGenerator.newProxyInstance(Thread.currentThread().getContextClassLoader(), target.getClass(), new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                PerformanceMonitor.begin(target.getClass().getName() + '.' + method.getName());
                // 执行原始方法
                Object result = method.invoke(target, args);
                PerformanceMonitor.end();
                return result;
            }
        });

        proxy.doSome22("GlassFish");
    }

    @Test
    public void testProxy() throws Exception {
        // 创建 ProxyFactory实例，用来创建代理类
        ProxyFactory factory = new ProxyFactory();
        factory.setSuperclass(TargetImpl.class);
        // factory.writeDirectory = "d:/";
        // factory.writeDirectory = Paths.get("").toAbsolutePath().toString();

        // 设置 Filter，用于筛选需要增强的方法
        factory.setFilter(new MethodFilter() {
            @Override
            public boolean isHandled(Method m) {
                return m.getName().equals("doSome22");
            }
        });

        // 生成代理类，并根据代理类创建代理对象
        Class<?> clazz = factory.createClass();
        TargetImpl proxy = (TargetImpl) clazz.newInstance();

        // 设置增强逻辑，被拦截的方法会执行 MethodHandler 中的逻辑
        ((Proxy) proxy).setHandler(new JavassistAdvice());
        proxy.doSome(99);

        // 执行 doSome22() 方法时会被拦截，进而执行代理逻辑
        System.out.println(proxy.doSome22("Jetty"));
    }

}
